/*
 * src/lexical/preprocess.c
 * 
 * Harry Wei <harryxiyou@gmail.com> (C) 2012
 *
 * Preprocess strings, these codes are under GPL.
 */
#include <stdio.h>
#include <glib.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "cp_ctrl.h"

static int remove_notes(char *buf) {
	/* XXX Can not support '//' notes style */
	g_message("enter func %s", __func__);
	if (NULL == buf) {
		g_message("%s -- Parameter Error!", __func__);
		return -1;
	}
	gchar **v = NULL;
	gchar buff[BUF_LEN];
	memset(buff, '\0', BUF_LEN);
//	g_message("%s -- /* ... */", __func__);
	v = g_strsplit(buf, "/*", 1024);
//	g_message("%s -- length of v is [%d]", __func__, g_strv_length(v));
	int i = 0;
	int tmp = 0;
	for (i = 0; i < g_strv_length(v); i++) {
	//	g_message("%s -- v[%d]'s contents [%s]", __func__, i, v[i]);
		gchar **_v = NULL;
		_v = g_strsplit(v[i], "*/", 1024);
	//	g_message("%s -- length of _v is [%d]", __func__, g_strv_length(_v));
		if (0 == g_strv_length(_v)) {
			g_strfreev(_v);
			continue;
		}
		for (tmp = 0; tmp < g_strv_length(_v); tmp++) {
			if (0 == tmp) {
				/* Notes contents, we do not need */
				continue;
			}
	//		g_message("%s -- _v[%d]'s contents [%s]", __func__, tmp, _v[tmp]);
			sprintf(buff, "%s%s", buff, _v[tmp]);
		}
		g_strfreev(_v);
	}
	g_strfreev(v);
	memset(buf, '\0', BUF_LEN);
	g_strlcpy(buf, buff, BUF_LEN);
	//g_message("%s -- buff is [%s]", __func__, buff);
	g_message("leave func %s", __func__);
	return 0;
}

static int remove_headers(char *buf) {
	/* XXX Can not include header file's contents, only remove them */
	g_message("enter func %s", __func__);
	if (NULL == buf) {
		g_message("%s -- Parameter Error!", __func__);
		return -1;
	}
	/* ??? no need */
	gchar **v = NULL;
	gchar buff[BUF_LEN];
	memset(buff, '\0', BUF_LEN);
	v = g_strsplit(buf, "#include", 1024);
	g_message("%s -- v[%d]'s contents are [%s]", __func__, 
									g_strv_length(v) - 1, 
									v[g_strv_length(v) - 1]);
	gchar **_v = NULL;
	/* XXX must be 'int' decorate a function, standard one */
	_v = g_strsplit(v[g_strv_length(v) - 1], "int", 2);
	//g_message("%s -- length of _v is [%d]", __func__, g_strv_length(_v));
	//g_message("%s -- _v[0]'s contents [%s]", __func__, _v[0]);
	sprintf(buff, "%s%s", "int", _v[g_strv_length(_v) - 1]);
	g_strfreev(_v);
	g_strfreev(v);
	memset(buf, '\0', BUF_LEN);
	g_strlcpy(buf, buff, BUF_LEN);
	g_message("%s -- buf contents are [%s]", __func__, buf);
	int ret = 0;
	return ret;
}

static int compress2words(struct la *ctrl, char *buf) {
	/*XXX Bug algorithm, just for simple now:
	 * arithmatic operator should be added later
	  */
	g_message("enter func %s", __func__);
	int ret = 0;
	int flag = 0;
	char *ch = buf;
	memset(ctrl->buff, '\0', BUF_LEN);
	char va_buff[BUF_LEN];
	memset(va_buff, '\0', BUF_LEN);
	while (1) {
		if ('\0' == *ch) {
			break;
		}
		g_message("%s -- parser character is %c", __func__, *ch);
		if ((('{' != *ch) && (' ' != *ch) &&
				('}' != *ch) && (';' != *ch)) &&
				('(' != *ch) && (')' != *ch) &&
				(',' != *ch) && ('	' != *ch) &&
				('"' != *ch)) {
			char tmp = *(ch + 1);
			g_message("%s -- parser ++character is %c", __func__, tmp);
			if (('{' == tmp) || (' ' == tmp) || 
						('}' == tmp) || (';' == tmp) ||
						('(' == tmp) || (')' == tmp) ||
						(',' == tmp) || ('	' == tmp) ||
						('"' == tmp)) {
				gchar **v = NULL;
				g_message("%s -- spilit one is %c", __func__, tmp);
				v = g_strsplit(buf, &tmp, 2);
				g_message("%s -- length of v is [%d]", __func__, g_strv_length(v));
				g_message("%s -- v[0] is [%s]", __func__, v[0]);
				g_message("%s -- v[1] is [%s]", __func__, v[1]);
				if (0 == flag) {
					//sprintf(ctrl->buff, "%s ", v[0]);
					g_strlcpy(ctrl->buff, v[0], BUF_LEN);
					g_message("%s -- 999 ctrl_buff is [%s]", __func__, ctrl->buff);
					flag = 1;
				} else {
					sprintf(ctrl->buff, "%s%s ", ctrl->buff, v[0]);
				}
				sprintf(ctrl->buff, "%s%c ", ctrl->buff, tmp);
				g_message("%s -- 999 ctrl_buff is [%s]", __func__, ctrl->buff);
				memset(buf, '\0', BUF_LEN);
				g_strlcpy(buf, v[1], BUF_LEN);
				g_message("%s -- 999 buf is [%s]", __func__, buf);
				ch = buf;
				if (('{' == *ch) || ('}' == *ch) || 
						(';' == *ch) || ('(' == *ch) || 
						(')' == *ch) || (',' == *ch) || 
						('"' == *ch)) {
					g_message("%s -- *ch is %c", __func__, *ch);
					sprintf(ctrl->buff, "%s%c ", ctrl->buff, *ch);
					*ch = ' ';
				} else {
					g_strfreev(v);
					continue;
				}
				g_message("%s -- result buff is [%s]", __func__, ctrl->buff);
				g_strfreev(v);
			}
		}
		ch += 1;
	}
	g_message("%s -- Last buff is [%s]", __func__, ctrl->buff);
	g_message("leave func %s", __func__);
	return ret;
}

int preprocess(struct la *ctrl) {
	g_message("enter func %s", __func__);
	if (NULL == ctrl || NULL == ctrl->buff) {
		g_message("%s -- Parameter error!", __func__);
		return -1;
	}
	int ret = 0;
	char buf[BUF_LEN];
	memset(buf, '\0', BUF_LEN);
	g_strlcpy(buf, ctrl->buff, BUF_LEN);
	ret = remove_notes(buf);
	g_message("%s -- ret is [%d]", __func__, ret);
	g_assert(ret == 0);
	ret = remove_headers(buf);
	g_assert(ret == 0);
	ret = compress2words(ctrl, buf);
	g_assert(ret == 0);
	g_message("leave func %s", __func__);
	return 0;
}
